Frigör kraften i ÄteranvÀndbar logik i dina React-applikationer med anpassade krokar. LÀr dig hur du skapar och anvÀnder anpassade krokar för renare och mer underhÄllbar kod.
Anpassade Krokar: à teranvÀndbara Logikmönster i React
React Hooks revolutionerade sÀttet vi skriver React-komponenter pÄ genom att introducera tillstÄnd och livscykelfunktioner i funktionella komponenter. Bland de mÄnga fördelarna de erbjuder, utmÀrker sig anpassade krokar som en kraftfull mekanism för att extrahera och ÄteranvÀnda logik över flera komponenter. Detta blogginlÀgg kommer att djupdyka i vÀrlden av anpassade krokar, och utforska deras fördelar, skapande och anvÀndning med praktiska exempel.
Vad Àr Anpassade Krokar?
I grund och botten Àr en anpassad krok en JavaScript-funktion som börjar med ordet "use" och kan anropa andra krokar. De lÄter dig extrahera komponentlogik till ÄteranvÀndbara funktioner. Detta Àr ett kraftfullt sÀtt att dela tillstÄndsbaserad logik, sidoeffekter eller andra komplexa beteenden mellan komponenter utan att behöva anvÀnda render props, högre ordningens komponenter eller andra komplexa mönster.
Nyckelegenskaper för Anpassade Krokar:
- Namnkonvention: Anpassade krokar mÄste börja med ordet "use". Detta signalerar till React att funktionen innehÄller krokar och ska följa reglerna för krokar.
- à teranvÀndbarhet: Det primÀra syftet Àr att kapsla in ÄteranvÀndbar logik, vilket gör det enkelt att dela funktionalitet mellan komponenter.
- TillstÄndsbaserad Logik: Anpassade krokar kan hantera sitt eget tillstÄnd med hjÀlp av
useState
-kroken, vilket gör att de kan kapsla in komplext tillstÄndsbaserat beteende. - Sidoeffekter: De kan ocksÄ utföra sidoeffekter med hjÀlp av
useEffect
-kroken, vilket möjliggör integration med externa API:er, datahÀmtning och mer. - Komponerbara: Anpassade krokar kan anropa andra krokar, vilket gör att du kan bygga komplex logik genom att komponera mindre, mer fokuserade krokar.
Fördelar med att AnvÀnda Anpassade Krokar
Anpassade krokar erbjuder flera betydande fördelar i React-utveckling:
- à teranvÀndning av Kod: Den mest uppenbara fördelen Àr förmÄgan att ÄteranvÀnda logik över flera komponenter. Detta minskar kodduplicering och frÀmjar en mer DRY (Don't Repeat Yourself) kodbas.
- FörbÀttrad LÀsbarhet: Genom att extrahera komplex logik till separata anpassade krokar blir dina komponenter renare och lÀttare att förstÄ. KÀrnlogiken i komponenten förblir fokuserad pÄ att rendera UI:t.
- FörbÀttrad UnderhÄllbarhet: NÀr logik Àr inkapslad i anpassade krokar kan Àndringar och buggfixar appliceras pÄ en enda plats, vilket minskar risken för att introducera fel i flera komponenter.
- Testbarhet: Anpassade krokar kan enkelt testas isolerat, vilket sÀkerstÀller att den ÄteranvÀndbara logiken fungerar korrekt oberoende av de komponenter som anvÀnder dem.
- Förenklade Komponenter: Anpassade krokar hjÀlper till att rensa upp i komponenter, vilket gör dem mindre mÄngordiga och mer fokuserade pÄ sitt primÀra syfte.
Skapa Din Första Anpassade Krok
LÄt oss illustrera skapandet av en anpassad krok med ett praktiskt exempel: en krok som spÄrar fönsterstorleken.
Exempel: useWindowSize
Denna krok kommer att returnera den aktuella bredden och höjden pÄ webblÀsarfönstret. Den kommer ocksÄ att uppdatera dessa vÀrden nÀr fönstret storleksÀndras.
import { useState, useEffect } from 'react';
function useWindowSize() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
function handleResize() {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
window.addEventListener('resize', handleResize);
// Ta bort hÀndelselyssnare vid stÀdning
return () => window.removeEventListener('resize', handleResize);
}, []); // Tom array sÀkerstÀller att effekten endast körs vid montering
return windowSize;
}
export default useWindowSize;
Förklaring:
- Importera NödvÀndiga Krokar: Vi importerar
useState
ochuseEffect
frÄn React. - Definiera Kroken: Vi skapar en funktion med namnet
useWindowSize
, enligt namnkonventionen. - Initiera TillstÄnd: Vi anvÀnder
useState
för att initierawindowSize
-tillstÄndet med fönstrets initiala bredd och höjd. - SÀtt Upp HÀndelselyssnare: Vi anvÀnder
useEffect
för att lÀgga till en 'resize'-hÀndelselyssnare pÄ fönstret. NÀr fönstret storleksÀndras uppdaterarhandleResize
-funktionenwindowSize
-tillstÄndet. - StÀdning: Vi returnerar en stÀdningsfunktion frÄn
useEffect
för att ta bort hÀndelselyssnaren nÀr komponenten avmonteras. Detta förhindrar minneslÀckor. - Returnera VÀrden: Kroken returnerar
windowSize
-objektet, som innehÄller fönstrets aktuella bredd och höjd.
AnvÀnda den Anpassade Kroken i en Komponent
Nu nÀr vi har skapat vÄr anpassade krok, lÄt oss se hur man anvÀnder den i en React-komponent.
import React from 'react';
import useWindowSize from './useWindowSize';
function MyComponent() {
const { width, height } = useWindowSize();
return (
Window width: {width}px
Window height: {height}px
);
}
export default MyComponent;
Förklaring:
- Importera Kroken: Vi importerar den anpassade kroken
useWindowSize
. - Anropa Kroken: Vi anropar
useWindowSize
-kroken inuti komponenten. - Ă
tkomst till VÀrden: Vi destrukurerar det returnerade objektet för att fÄ
width
- ochheight
-vÀrdena. - Rendera VÀrden: Vi renderar bredd- och höjdvÀrdena i komponentens UI.
Alla komponenter som anvÀnder useWindowSize
kommer automatiskt att uppdateras nÀr fönsterstorleken Àndras.
Mer Komplexa Exempel
LÄt oss utforska nÄgra mer avancerade anvÀndningsfall för anpassade krokar.
Exempel: useLocalStorage
Denna krok lÄter dig enkelt lagra och hÀmta data frÄn local storage.
import { useState, useEffect } from 'react';
function useLocalStorage(key, initialValue) {
// TillstÄnd för att lagra vÄrt vÀrde
// Skicka initialvÀrde till useState sÄ att logiken bara körs en gÄng
const [storedValue, setStoredValue] = useState(() => {
try {
// HÀmta frÄn local storage med nyckel
const item = window.localStorage.getItem(key);
// Parsa lagrad json eller returnera initialValue om ingen finns
return item ? JSON.parse(item) : initialValue;
} catch (error) {
// Om fel, returnera ocksÄ initialValue
console.log(error);
return initialValue;
}
});
// Returnera en inlindad version av useStates setter-funktion som ...
// ... sparar det nya vÀrdet till localStorage.
const setValue = (value) => {
try {
// TillÄt att vÀrdet Àr en funktion sÄ att vi har samma API som useState
const valueToStore = value instanceof Function ? value(storedValue) : value;
// Spara till local storage
window.localStorage.setItem(key, JSON.stringify(valueToStore));
// Spara tillstÄnd
setStoredValue(valueToStore);
} catch (error) {
// En mer avancerad implementation skulle hantera fel fallet
console.log(error);
}
};
useEffect(() => {
try {
const item = window.localStorage.getItem(key);
setStoredValue(item ? JSON.parse(item) : initialValue);
} catch (error) {
console.log(error);
}
}, [key, initialValue]);
return [storedValue, setValue];
}
export default useLocalStorage;
AnvÀndning:
import React from 'react';
import useLocalStorage from './useLocalStorage';
function MyComponent() {
const [name, setName] = useLocalStorage('name', 'Guest');
return (
Hello, {name}!
setName(e.target.value)}
/>
);
}
export default MyComponent;
Exempel: useFetch
Denna krok kapslar in logiken för att hÀmta data frÄn ett API.
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const json = await response.json();
setData(json);
setLoading(false);
} catch (error) {
setError(error);
setLoading(false);
}
}
fetchData();
}, [url]);
return { data, loading, error };
}
export default useFetch;
AnvÀndning:
import React from 'react';
import useFetch from './useFetch';
function MyComponent() {
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/todos/1');
if (loading) return Loading...
;
if (error) return Error: {error.message}
;
return (
Title: {data.title}
Completed: {data.completed ? 'Yes' : 'No'}
);
}
export default MyComponent;
BÀsta Praxis för Anpassade Krokar
För att sÀkerstÀlla att dina anpassade krokar Àr effektiva och underhÄllbara, följ dessa bÀsta praxis:
- HÄll Dem Fokuserade: Varje anpassad krok bör ha ett enda, vÀldefinierat syfte. Undvik att skapa överdrivet komplexa krokar som försöker göra för mycket.
- Dokumentera Dina Krokar: TillhandahÄll tydlig och koncis dokumentation för varje anpassad krok, dÀr du förklarar dess syfte, indata och utdata.
- Testa Dina Krokar: Skriv enhetstester för dina anpassade krokar för att sÀkerstÀlla att de fungerar korrekt och pÄlitligt.
- AnvÀnd Beskrivande Namn: VÀlj beskrivande namn för dina anpassade krokar som tydligt indikerar deras syfte.
- Hantera Fel Elegant: Implementera felhantering inom dina anpassade krokar för att förhindra ovÀntat beteende och ge informativa felmeddelanden.
- TÀnk pÄ à teranvÀndbarhet: Designa dina anpassade krokar med ÄteranvÀndbarhet i Ätanke. Gör dem tillrÀckligt generiska för att kunna anvÀndas i flera komponenter.
- Undvik Ăverabstraktion: Skapa inte anpassade krokar för enkel logik som lĂ€tt kan hanteras inom en komponent. Extrahera endast logik som Ă€r verkligt Ă„teranvĂ€ndbar och komplex.
Vanliga Fallgropar att Undvika
- Bryta mot Reglerna för Krokar: Anropa alltid krokar pÄ den översta nivÄn i din anpassade krokfunktion och anropa dem endast frÄn React-funktionskomponenter eller andra anpassade krokar.
- Ignorera Beroenden i useEffect: Se till att inkludera alla nödvÀndiga beroenden i beroendearrayen för
useEffect
-kroken för att förhindra inaktuella closures och ovÀntat beteende. - Skapa OÀndliga Loopar: Var försiktig nÀr du uppdaterar tillstÄnd inom en
useEffect
-krok, eftersom detta lÀtt kan leda till oÀndliga loopar. Se till att uppdateringen Àr villkorlig och baserad pÄ Àndringar i beroenden. - Glömma StÀdning: Inkludera alltid en stÀdningsfunktion i
useEffect
för att ta bort hÀndelselyssnare, avbryta prenumerationer och utföra andra stÀdningsuppgifter för att förhindra minneslÀckor.
Avancerade Mönster
Komponera Anpassade Krokar
Anpassade krokar kan komponeras tillsammans för att skapa mer komplex logik. Till exempel kan du kombinera en useLocalStorage
-krok med en useFetch
-krok för att automatiskt spara hÀmtad data till local storage.
Dela Logik Mellan Krokar
Om flera anpassade krokar delar gemensam logik kan du extrahera den logiken till en separat hjÀlpfunktion och ÄteranvÀnda den i bÄda krokarna.
AnvÀnda Context med Anpassade Krokar
Anpassade krokar kan anvÀndas tillsammans med React Context för att komma Ät och uppdatera globalt tillstÄnd. Detta lÄter dig skapa ÄteranvÀndbara komponenter som Àr medvetna om och kan interagera med applikationens globala tillstÄnd.
Verkliga Exempel
HÀr Àr nÄgra exempel pÄ hur anpassade krokar kan anvÀndas i verkliga applikationer:
- FormulÀrvalidering: Skapa en
useForm
-krok för att hantera formulÀrtillstÄnd, validering och inskickning. - Autentisering: Implementera en
useAuth
-krok för att hantera anvÀndarautentisering och auktorisering. - Temahantering: Utveckla en
useTheme
-krok för att vÀxla mellan olika teman (ljust, mörkt, etc.). - Geolokalisering: Bygg en
useGeolocation
-krok för att spÄra anvÀndarens nuvarande position. - Scroll-detektering: Skapa en
useScroll
-krok för att upptÀcka nÀr anvÀndaren har scrollat till en viss punkt pÄ sidan.
Exempel : useGeolocation-krok för tvÀrkulturella applikationer som karttjÀnster eller leveranstjÀnster
import { useState, useEffect } from 'react';
function useGeolocation() {
const [location, setLocation] = useState({
latitude: null,
longitude: null,
error: null,
});
useEffect(() => {
if (!navigator.geolocation) {
setLocation({
latitude: null,
longitude: null,
error: 'Geolocation is not supported by this browser.',
});
return;
}
const watchId = navigator.geolocation.watchPosition(
(position) => {
setLocation({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null,
});
},
(error) => {
setLocation({
latitude: null,
longitude: null,
error: error.message,
});
}
);
return () => navigator.geolocation.clearWatch(watchId);
}, []);
return location;
}
export default useGeolocation;
Slutsats
Anpassade krokar Àr ett kraftfullt verktyg för att skriva renare, mer ÄteranvÀndbar och mer underhÄllbar React-kod. Genom att kapsla in komplex logik i anpassade krokar kan du förenkla dina komponenter, minska kodduplicering och förbÀttra den övergripande strukturen i dina applikationer. Omfamna anpassade krokar och frigör deras potential att bygga mer robusta och skalbara React-applikationer.
Börja med att identifiera omrÄden i din befintliga kodbas dÀr logik upprepas över flera komponenter. Refaktorera sedan den logiken till anpassade krokar. Med tiden kommer du att bygga ett bibliotek av ÄteranvÀndbara krokar som kommer att pÄskynda din utvecklingsprocess och förbÀttra kvaliteten pÄ din kod.
Kom ihÄg att följa bÀsta praxis, undvika vanliga fallgropar och utforska avancerade mönster för att fÄ ut det mesta av anpassade krokar. Med övning och erfarenhet kommer du att bli en mÀstare pÄ anpassade krokar och en mer effektiv React-utvecklare.